#pragma once

#ifdef __cplusplus
struct arg_parsing_exception {};
#endif
#include <stdlib.h>
#include <string.h>

struct cmdline_arg
{
	bool set;
	char const *name;
	virtual void get_value (char const*) = 0;  
	virtual char const* type_string() = 0;
};

template <typename arg_val_t>
struct cmdline_arg_t : cmdline_arg
{
	arg_val_t& val;
	void get_value (char const* val_string);
	char const *type_string();

	cmdline_arg_t(arg_val_t& dummy) : val(dummy) {}

	cmdline_arg_t (char const *n, arg_val_t& v) : val(v) {
		cmdline_arg::name = n; 
		cmdline_arg::set = false;
	}
};

template <typename arg_val_t>
struct list_arg_t : cmdline_arg
{
	arg_val_t *& vals;
	int &list_len;
	char const *sep;

	list_arg_t (char const *n, arg_val_t *& v, int& l, char const *s)
		: vals(v), list_len(l), sep(s)
	{
		cmdline_arg::name = n;
	}

	void get_value (char const* val_string);
	char const *type_string ();
};

template <typename arg_val_t> void list_arg_t<arg_val_t>::
get_value (char const* val_string)
{
	char *t0 = strdup (val_string), *t = t0, **tt = &t, *s;

	list_len = 0;

	while (0 != (s = strsep (tt, sep))){
		++list_len;
	}

	strcpy (t0, val_string);
	t = t0; tt = &t;

	vals = new arg_val_t [list_len];

	int i = 0;
	while (0 != (s = strsep (tt, sep)))
	{
		cmdline_arg *a = new cmdline_arg_t<arg_val_t> (0, vals[i++]);
		a->get_value (s);
		delete a;
	}

	free (t);
}

template <typename arg_val_t> char const* list_arg_t<arg_val_t>::
type_string () {
	arg_val_t tmp;
	static char buf [1024] = "";
	strcpy (buf, cmdline_arg_t<arg_val_t>(tmp).type_string());
	strcat (buf, " list [");
	strcat (buf, this->sep);
	strcat (buf, "]");
	return buf;
}



extern void get_args (struct cmdline_arg *args[],
                             char const *argstring,
                             char const *argsep);

